// const path = require('path');
// const ESLintPlugin = require('eslint-webpack-plugin');
import path from "path";
import ESLintWebpackPlugin from 'eslint-webpack-plugin';
import HtmlWebpackPlugin from "html-webpack-plugin";
import {fileURLToPath} from "url";
import MiniCssExtractPlugin from "mini-css-extract-plugin";
import CssMinimizerPlugin from "css-minimizer-webpack-plugin";
import TerserPlugin from 'terser-webpack-plugin';
import os from 'os'
import ImageMinimizerPlugin from "image-minimizer-webpack-plugin";
import PreloadWebpackPlugin from "@vue/preload-webpack-plugin";
import WorkboxPlugin from "workbox-webpack-plugin";

const threads = os.cpus().length


const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
    return [
        MiniCssExtractPlugin.loader,
        "css-loader",
        {
            loader: "postcss-loader",
            options: {
                postcssOptions: {
                    plugins: [
                        "postcss-preset-env", // 能解决大多数样式兼容性问题
                    ],
                },
            },
        },
        preProcessor,
    ].filter(Boolean); // filter过滤掉空值(preProcessor没有传值时)
};

export default {
    entry: './src/main.js', output: {
        path: path.resolve(__dirname, '../dist'), // __dirname是nodejs的变量 表示当前文件所在目录的绝对路径
        // [contenthash:8]使用contenthash，取8位长度
        filename: "static/js/[name].[contenthash:8].js", // 入口文件打包输出资源命名方式
        chunkFilename: "static/js/[name].[contenthash:8].chunk.js", // 动态导入输出资源命名方式
        assetModuleFilename: "static/media/[name].[hash:8][ext]", // 图片、字体等资源命名方式（注意用hash）
        clean: true, // 自动将上次打包目录资源清空
    }, module: {
        rules: [
            {
                oneOf: [ // 每个文件只能被其中一个loader配置处理，提高打包速度
                    {
                        test: /\.css$/, use: ['style-loader', 'css-loader'], // 执行顺序从右到左从下到上
                    }, {
                        test: /\.less$/, use: [// compiles Less to CSS
                            'style-loader', 'css-loader', 'less-loader',],
                    }, {
                        test: /\.s[ac]ss$/, use: [// 将 JS 字符串生成为 style 节点
                            'style-loader', // 将 CSS 转化成 CommonJS 模块
                            'css-loader', // 将 Sass 编译成 CSS
                            'sass-loader',],
                    }, {
                        test: /\.styl$/, use: [// 将 JS 字符串生成为 style 节点
                            'style-loader', // 将 CSS 转化成 CommonJS 模块
                            'css-loader', // 将 Sass 编译成 CSS
                            'stylus-loader',],
                    }, {
                        test: /\.(png|jpe?g|gif|webp)$/, type: "asset", parser: {
                            dataUrlCondition: {
                                maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                                // 优点：减少请求数量
                                // 缺点：图片体积会变大
                            }
                        },
                        // generator: {
                        //     // 将图片文件输出到 static/imgs 目录中
                        //     // 将图片文件命名 [hash:8][ext][query]
                        //     // [hash:8]: hash值取8位
                        //     // [ext]: 使用之前的文件扩展名
                        //     // [query]: 添加之前的query参数
                        //     filename: "static/imgs/[hash:8][ext][query]",
                        // },
                    }, {
                        test: /\.(ttf|woff2?|mp4|mp3|avi)$/, type: "asset/resource",
                        // generator: {
                        //     filename: "static/media/[hash:8][ext][query]",
                        // },
                    }, {
                        test: /\.js$/,
                        // exclude: /node_modules/, // 排除node_modules代码不编译
                        include: path.resolve(__dirname, "../src"), // 也可以用包含
                        use: [
                            {
                                loader: "thread-loader", // 开启多进程
                                options: {
                                    workers: threads, // 数量
                                },
                            },
                            {
                                loader: "babel-loader",
                                options: {
                                    cacheDirectory: true, // 开启babel编译缓存
                                    cacheCompression: false, // 缓存文件不要压缩
                                    plugins: ["@babel/plugin-transform-runtime"], // 减少代码体积
                                },
                            },
                        ],
                    },
                ]
            }
        ]
    },
    plugins: [
        new ESLintWebpackPlugin({
            // 指定检查文件的根目录
            context: path.resolve(__dirname, "../src"), // 指定检查文件的根目录
            exclude: "node_modules",
            cache: true,
            cacheLocation: path.resolve(
                __dirname,
                "../node_modules/.cache/.eslintcache"
            ),
            threads, // 开启多进程
        }),
        new HtmlWebpackPlugin({
            // 以 public/index.html 为模板创建文件
            // 新的html文件有两个特点：1. 内容和源文件一致 2. 自动引入打包生成的js等资源
            template: path.resolve(__dirname, "../public/index.html"),
        }),
        new MiniCssExtractPlugin({
            // 定义输出文件名和目录
            filename: "static/css/[name].[contenthash:8].css",
            chunkFilename: "static/css/[name].[contenthash:8].chunk.css",
        }),
        // css压缩
        // new CssMinimizerPlugin(),
        new PreloadWebpackPlugin({
            // rel: "preload", // preload兼容性更好
            // as: "script",
            rel: 'prefetch' // prefetch兼容性更差
        }),
        new WorkboxPlugin.GenerateSW({
            // 这些选项帮助快速启用 ServiceWorkers
            // 不允许遗留任何“旧的” ServiceWorkers
            clientsClaim: true,
            skipWaiting: true,
        }),
    ],
    optimization: {
        minimize: true,
        minimizer: [
            // css压缩也可以写到optimization.minimizer里面，效果一样的
            new CssMinimizerPlugin(),
            // 当生产模式会默认开启TerserPlugin，但是我们需要进行其他配置，就要重新写了
            new TerserPlugin({
                parallel: threads // 开启多进程
            }),
            // 压缩图片
            new ImageMinimizerPlugin({
                minimizer: {
                    implementation: ImageMinimizerPlugin.imageminGenerate,
                    options: {
                        plugins: [
                            ["gifsicle", {interlaced: true}],
                            ["jpegtran", {progressive: true}],
                            ["optipng", {optimizationLevel: 5}],
                            [
                                "svgo",
                                {
                                    plugins: [
                                        "preset-default",
                                        "prefixIds",
                                        {
                                            name: "sortAttrs",
                                            params: {
                                                xmlnsOrder: "alphabetical",
                                            },
                                        },
                                    ],
                                },
                            ],
                        ],
                    },
                },
            }),
        ],
        // 提取runtime文件
        runtimeChunk: {
            name: (entrypoint) => `runtime~${entrypoint.name}`, // runtime文件命名规则
        },
    },
    // // 开发服务器 生产模式不需要devServer
    // devServer: {
    //     host: "localhost", // 启动服务器域名
    //     port: "3000", // 启动服务器端口号
    //     open: true, // 是否自动打开浏览器
    // },
    mode: "production",
    devtool: "source-map", // 包含行/列映射,打包编译速度更慢
}